home *** CD-ROM | disk | FTP | other *** search
/ Inter.Net 55-1 / Inter.Net 55-1.iso / CBuilder / Setup / BCB / data.z / atlctl.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-02-09  |  30.3 KB  |  1,181 lines

  1. // This is a part of the Active Template Library.
  2. // Copyright (C) 1996-1997 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Active Template Library Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Active Template Library product.
  10.  
  11. #ifndef ATL_NO_NAMESPACE
  12. namespace ATL
  13. {
  14. #endif
  15.  
  16. /////////////////////////////////////////////////////////////////////////////
  17. // CComDispatchDriver support
  18.  
  19. HRESULT CComDispatchDriver::GetProperty(IDispatch* pDisp, DISPID dwDispID,
  20.     VARIANT* pVar)
  21. {
  22.     ATLTRACE(_T("CPropertyHelper::GetProperty\n"));
  23.     DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
  24.     return pDisp->Invoke(dwDispID, IID_NULL,
  25.             LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
  26.             &dispparamsNoArgs, pVar, NULL, NULL);
  27. }
  28.  
  29. HRESULT CComDispatchDriver::PutProperty(IDispatch* pDisp, DISPID dwDispID,
  30.     VARIANT* pVar)
  31. {
  32.     ATLTRACE(_T("CPropertyHelper::PutProperty\n"));
  33.     DISPPARAMS dispparams = {NULL, NULL, 1, 1};
  34.     dispparams.rgvarg = pVar;
  35.     DISPID dispidPut = DISPID_PROPERTYPUT;
  36.     dispparams.rgdispidNamedArgs = &dispidPut;
  37.  
  38.     if (pVar->vt == VT_UNKNOWN || pVar->vt == VT_DISPATCH || 
  39.         (pVar->vt & VT_ARRAY) || (pVar->vt & VT_BYREF))
  40.     {
  41.         HRESULT hr = pDisp->Invoke(dwDispID, IID_NULL,
  42.             LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF,
  43.             &dispparams, NULL, NULL, NULL);
  44.         if (SUCCEEDED(hr))
  45.             return hr;
  46.     }
  47.  
  48.     return pDisp->Invoke(dwDispID, IID_NULL,
  49.             LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT,
  50.             &dispparams, NULL, NULL, NULL);
  51. }
  52.  
  53. //////////////////////////////////////////////////////////////////////////////
  54. // CFirePropNotifyEvent
  55.  
  56. HRESULT CFirePropNotifyEvent::FireOnRequestEdit(IUnknown* pUnk, DISPID dispID)
  57. {
  58.     CComQIPtr<IConnectionPointContainer, &IID_IConnectionPointContainer> pCPC(pUnk);
  59.     if (!pCPC)
  60.         return S_OK;
  61.     CComPtr<IConnectionPoint> pCP;
  62.     pCPC->FindConnectionPoint(IID_IPropertyNotifySink, &pCP);
  63.     if (!pCP)
  64.         return S_OK;
  65.     CComPtr<IEnumConnections> pEnum;
  66.  
  67.     if (FAILED(pCP->EnumConnections(&pEnum)))
  68.         return S_OK;
  69.     CONNECTDATA cd;
  70.     while (pEnum->Next(1, &cd, NULL) == S_OK)
  71.     {
  72.         if (cd.pUnk)
  73.         {
  74.             HRESULT hr = S_OK;
  75.             CComQIPtr<IPropertyNotifySink, &IID_IPropertyNotifySink> pSink(cd.pUnk);
  76.             if (pSink)
  77.                 hr = pSink->OnRequestEdit(dispID);
  78.             cd.pUnk->Release();
  79.             if (hr == S_FALSE)
  80.                 return S_FALSE;
  81.         }
  82.     }
  83.     return S_OK;
  84. }
  85.  
  86. HRESULT CFirePropNotifyEvent::FireOnChanged(IUnknown* pUnk, DISPID dispID)
  87. {
  88.     CComQIPtr<IConnectionPointContainer, &IID_IConnectionPointContainer> pCPC(pUnk);
  89.     if (!pCPC)
  90.         return S_OK;
  91.     CComPtr<IConnectionPoint> pCP;
  92.     pCPC->FindConnectionPoint(IID_IPropertyNotifySink, &pCP);
  93.     if (!pCP)
  94.         return S_OK;
  95.     CComPtr<IEnumConnections> pEnum;
  96.  
  97.     if (FAILED(pCP->EnumConnections(&pEnum)))
  98.         return S_OK;
  99.     CONNECTDATA cd;
  100.     while (pEnum->Next(1, &cd, NULL) == S_OK)
  101.     {
  102.         if (cd.pUnk)
  103.         {
  104.             CComQIPtr<IPropertyNotifySink, &IID_IPropertyNotifySink> pSink(cd.pUnk);
  105.             if (pSink)
  106.                 pSink->OnChanged(dispID);
  107.             cd.pUnk->Release();
  108.         }
  109.     }
  110.     return S_OK;
  111. }
  112.  
  113. /////////////////////////////////////////////////////////////////////////////
  114. // Control support
  115.  
  116. HRESULT CComControlBase::IQuickActivate_QuickActivate(QACONTAINER *pQACont,
  117.     QACONTROL *pQACtrl)
  118. {
  119.     _ASSERTE(pQACont != NULL);
  120.     _ASSERTE(pQACtrl != NULL);
  121.     _ASSERTE(pQACont->cbSize >= sizeof(QACONTAINER));
  122.     _ASSERTE(pQACtrl->cbSize >= sizeof(QACONTROL));
  123.  
  124.     if (!pQACont || !pQACtrl)
  125.         return E_POINTER;
  126.  
  127.     HRESULT hRes;
  128.     memset(pQACtrl, 0, sizeof(QACONTROL));
  129.     pQACtrl->cbSize = sizeof(QACONTROL);
  130.  
  131.     // get all interfaces we are going to need
  132.     CComPtr<IOleObject> pOO;
  133.     ControlQueryInterface(IID_IOleObject, (void**)&pOO);
  134.     CComPtr<IViewObjectEx> pVOEX;
  135.     ControlQueryInterface(IID_IViewObjectEx, (void**)&pVOEX);
  136.     CComPtr<IPointerInactive> pPI;
  137.     ControlQueryInterface(IID_IPointerInactive, (void**)&pPI);
  138.     CComPtr<IProvideClassInfo2> pPCI;
  139.     ControlQueryInterface(IID_IProvideClassInfo2, (void**)&pPCI);
  140.  
  141.     if (pOO == NULL || pVOEX == NULL)
  142.         return E_FAIL;
  143.  
  144.     pOO->SetClientSite(pQACont->pClientSite);
  145.  
  146.     if (pQACont->pAdviseSink != NULL)
  147.     {
  148.         ATLTRACE(_T("Setting up IOleObject Advise\n"));
  149.         pVOEX->SetAdvise(DVASPECT_CONTENT, 0, pQACont->pAdviseSink);
  150.     }
  151.  
  152.     CComPtr<IConnectionPointContainer> pCPC;
  153.     ControlQueryInterface(IID_IConnectionPointContainer, (void**)&pCPC);
  154.  
  155.     if (pQACont->pPropertyNotifySink)
  156.     {
  157.         ATLTRACE(_T("Setting up PropNotify CP\n"));
  158.         CComPtr<IConnectionPoint> pCP;
  159.         if (pCPC != NULL)
  160.         {
  161.             hRes = pCPC->FindConnectionPoint(IID_IPropertyNotifySink, &pCP);
  162.             if (SUCCEEDED(hRes))
  163.                 pCP->Advise(pQACont->pPropertyNotifySink, &pQACtrl->dwPropNotifyCookie);
  164.         }
  165.     }
  166.  
  167.     if (pPCI)
  168.     {
  169.         GUID iidDefaultSrc;
  170.         if (SUCCEEDED(pPCI->GetGUID(GUIDKIND_DEFAULT_SOURCE_DISP_IID,
  171.             &iidDefaultSrc)))
  172.         {
  173.             if (pQACont->pUnkEventSink)
  174.             {
  175.                 ATLTRACE(_T("Setting up Default Out Going Interface\n"));
  176.                 CComPtr<IConnectionPoint> pCP;
  177.                 if (pCPC != NULL)
  178.                 {
  179.                     hRes = pCPC->FindConnectionPoint(iidDefaultSrc, &pCP);
  180.                     if (SUCCEEDED(hRes))
  181.                         pCP->Advise(pQACont->pUnkEventSink, &pQACtrl->dwEventCookie);
  182.                 }
  183.             }
  184.         }
  185.     }
  186.     // give information to container
  187.     if (pOO != NULL)
  188.         pOO->GetMiscStatus(DVASPECT_CONTENT, &pQACtrl->dwMiscStatus);
  189.  
  190.     if (pVOEX != NULL)
  191.         pVOEX->GetViewStatus(&pQACtrl->dwViewStatus);
  192.  
  193.     if (pPI != NULL)
  194.         pPI->GetActivationPolicy(&pQACtrl->dwPointerActivationPolicy);
  195.     return S_OK;
  196. }
  197.  
  198. HRESULT CComControlBase::IPersistPropertyBag_Load(LPPROPERTYBAG pPropBag,
  199.     LPERRORLOG pErrorLog, ATL_PROPMAP_ENTRY* pMap)
  200. {
  201.     USES_CONVERSION;
  202.     CComPtr<IDispatch> pDispatch;
  203.     const IID* piidOld = NULL;
  204.     for(int i = 0; pMap[i].pclsidPropPage != NULL; i++)
  205.     {
  206.         if (pMap[i].szDesc == NULL)
  207.             continue;
  208.         CComVariant var;
  209.  
  210.         if(pMap[i].piidDispatch != piidOld)
  211.         {
  212.             pDispatch.Release();
  213.             if(FAILED(ControlQueryInterface(*pMap[i].piidDispatch, (void**)&pDispatch)))
  214.             {
  215.                 ATLTRACE(_T("Failed to get a dispatch pointer for property #%i\n"), i);
  216.                 return E_FAIL;
  217.             }
  218.             piidOld = pMap[i].piidDispatch;
  219.         }
  220.  
  221.         if (FAILED(CComDispatchDriver::GetProperty(pDispatch, pMap[i].dispid, &var)))
  222.         {
  223.             ATLTRACE(_T("Invoked failed on DISPID %x\n"), pMap[i].dispid);
  224.             return E_FAIL;
  225.         }
  226.  
  227.         HRESULT hr = pPropBag->Read(pMap[i].szDesc, &var, pErrorLog);
  228.         if (FAILED(hr))
  229.         {
  230.             if (hr == E_INVALIDARG)
  231.             {
  232.                 ATLTRACE(_T("Property %s not in Bag\n"), OLE2CT(pMap[i].szDesc));
  233.             }
  234.             else
  235.             {
  236.                 // Many containers return different ERROR values for Member not found
  237.                 ATLTRACE(_T("Error attempting to read Property %s from PropertyBag \n"), OLE2CT(pMap[i].szDesc));
  238.             }
  239.             continue;
  240.         }
  241.  
  242.         if (FAILED(CComDispatchDriver::PutProperty(pDispatch, pMap[i].dispid, &var)))
  243.         {
  244.             ATLTRACE(_T("Invoked failed on DISPID %x\n"), pMap[i].dispid);
  245.             return E_FAIL;
  246.         }
  247.     }
  248.     return S_OK;
  249.  
  250. }
  251.  
  252. HRESULT CComControlBase::IPersistPropertyBag_Save(LPPROPERTYBAG pPropBag,
  253.     BOOL fClearDirty, BOOL /*fSaveAllProperties*/, ATL_PROPMAP_ENTRY* pMap)
  254. {
  255.     if (pPropBag == NULL)
  256.     {
  257.         ATLTRACE(_T("PropBag pointer passed in was invalid\n"));
  258.         return E_POINTER;
  259.     }
  260.  
  261.     CComPtr<IDispatch> pDispatch;
  262.     const IID* piidOld = NULL;
  263.     for(int i = 0; pMap[i].pclsidPropPage != NULL; i++)
  264.     {
  265.         if (pMap[i].szDesc == NULL)
  266.             continue;
  267.         CComVariant var;
  268.  
  269.         if(pMap[i].piidDispatch != piidOld)
  270.         {
  271.             pDispatch.Release();
  272.             if(FAILED(ControlQueryInterface(*pMap[i].piidDispatch, (void**)&pDispatch)))
  273.             {
  274.                 ATLTRACE(_T("Failed to get a dispatch pointer for property #%i\n"), i);
  275.                 return E_FAIL;
  276.             }
  277.             piidOld = pMap[i].piidDispatch;
  278.         }
  279.  
  280.         if (FAILED(CComDispatchDriver::GetProperty(pDispatch, pMap[i].dispid, &var)))
  281.         {
  282.             ATLTRACE(_T("Invoked failed on DISPID %x\n"), pMap[i].dispid);
  283.             return E_FAIL;
  284.         }
  285.  
  286.         if (var.vt == VT_UNKNOWN || var.vt == VT_DISPATCH)
  287.         {
  288.             if (var.punkVal == NULL)
  289.             {
  290.                 ATLTRACE(_T("Warning skipping empty IUnknown in Save\n"));
  291.                 continue;
  292.             }
  293.         }
  294.  
  295.         HRESULT hr = pPropBag->Write(pMap[i].szDesc, &var);
  296.         if (FAILED(hr))
  297.             return hr;
  298.     }
  299.     m_bRequiresSave = FALSE;
  300.     return S_OK;
  301. }
  302.  
  303. HRESULT CComControlBase::ISpecifyPropertyPages_GetPages(CAUUID* pPages,
  304.     ATL_PROPMAP_ENTRY* pMap)
  305. {
  306.     _ASSERTE(pMap != NULL);
  307.     int nCnt = 0;
  308.     // Get count of unique pages
  309.     for(int i = 0; pMap[i].pclsidPropPage != NULL; i++)
  310.     {
  311.         if (!InlineIsEqualGUID(*pMap[i].pclsidPropPage, CLSID_NULL))
  312.             nCnt++;
  313.     }
  314.     pPages->pElems = NULL;
  315.     pPages->pElems = (GUID*) CoTaskMemAlloc(sizeof(CLSID)*nCnt);
  316.     if (pPages->pElems == NULL)
  317.         return E_OUTOFMEMORY;
  318.     nCnt = 0;
  319. #if defined(BCC32_COMPAT) && !defined(__MFC_COMPAT__)
  320.         int i;
  321. #endif        
  322.     for(i = 0; pMap[i].pclsidPropPage != NULL; i++)
  323.     {
  324.         if (!InlineIsEqualGUID(*pMap[i].pclsidPropPage, CLSID_NULL))
  325.         {
  326.             BOOL bMatch = FALSE;
  327.             for (int j=0;j<nCnt;j++)
  328.             {
  329.                 if (InlineIsEqualGUID(*(pMap[i].pclsidPropPage), pPages->pElems[j]))
  330.                 {
  331.                     bMatch = TRUE;
  332.                     break;
  333.                 }
  334.             }
  335.             if (!bMatch)
  336.                 pPages->pElems[nCnt++] = *pMap[i].pclsidPropPage;
  337.         }
  338.     }
  339.     pPages->cElems = nCnt;
  340.     return S_OK;
  341. }
  342.  
  343. BOOL CComControlBase::SetControlFocus(BOOL bGrab)
  344. {
  345.     if (m_bWndLess)
  346.     {
  347.         if (!m_bUIActive && bGrab)
  348.             if (FAILED(InPlaceActivate(OLEIVERB_UIACTIVATE)))
  349.                 return FALSE;
  350.  
  351.         return (m_spInPlaceSite->SetFocus(bGrab) == S_OK);
  352.     }
  353.     else
  354.     {
  355.         // we've got a window.
  356.         //
  357.         if (m_bInPlaceActive)
  358.         {
  359.             HWND hwnd = (bGrab) ? m_hWndCD : ::GetParent(m_hWndCD);
  360.             if (!m_bUIActive && bGrab)
  361.                 return SUCCEEDED(InPlaceActivate(OLEIVERB_UIACTIVATE));
  362.             else
  363.                 return (::SetFocus(hwnd) != NULL);
  364.         }
  365.     }
  366.     return FALSE;
  367. }
  368.  
  369. HRESULT CComControlBase::DoVerbProperties(LPCRECT /* prcPosRect */, HWND hwndParent)
  370. {
  371.     HRESULT hr = S_OK;
  372.     CComQIPtr <ISpecifyPropertyPages, &IID_ISpecifyPropertyPages> spPages;
  373.     CComQIPtr <IOleObject, &IID_IOleObject> spObj;
  374.     CComQIPtr <IOleControlSite, &IID_IOleControlSite> spSite(m_spClientSite);
  375.  
  376.     if (spSite)
  377.     {
  378.         hr = spSite->ShowPropertyFrame();
  379.         if (SUCCEEDED(hr))
  380.             return hr;
  381.     }
  382.  
  383.     CComPtr<IUnknown> pUnk;
  384.     ControlQueryInterface(IID_IUnknown, (void**)&pUnk);
  385.     _ASSERTE(pUnk != NULL);
  386.     CAUUID pages;
  387.     spPages = pUnk;
  388.     if (spPages)
  389.     {
  390.         spPages->GetPages(&pages);
  391.         spObj = pUnk;
  392.         if (spObj)
  393.         {
  394.             LPOLESTR szTitle = NULL;
  395.  
  396.             spObj->GetUserType(USERCLASSTYPE_SHORT, &szTitle);
  397.  
  398.             hr = OleCreatePropertyFrame(hwndParent, m_rcPos.top, m_rcPos.left, szTitle,
  399.                 1, &pUnk.p, pages.cElems, pages.pElems, LOCALE_USER_DEFAULT, 0, 0);
  400.  
  401.             CoTaskMemFree(szTitle);
  402.         }
  403.         else
  404.         {
  405.             hr = OLEOBJ_S_CANNOT_DOVERB_NOW;
  406.         }
  407.     }
  408.     else
  409.     {
  410.         hr = OLEOBJ_S_CANNOT_DOVERB_NOW;
  411.     }
  412.  
  413.     return hr;
  414. }
  415.  
  416. HRESULT CComControlBase::InPlaceActivate(LONG iVerb, const RECT* prcPosRect)
  417. {
  418.     HRESULT hr;
  419.  
  420.     if (m_spClientSite == NULL)
  421.         return S_OK;
  422.  
  423.     CComPtr<IOleInPlaceObject> pIPO;
  424.     ControlQueryInterface(IID_IOleInPlaceObject, (void**)&pIPO);
  425.     _ASSERTE(pIPO != NULL);
  426.     if (prcPosRect != NULL)
  427.         pIPO->SetObjectRects(prcPosRect, prcPosRect);
  428.  
  429.     if (!m_bNegotiatedWnd)
  430.     {
  431.         if (!m_bWindowOnly)
  432.             // Try for windowless site
  433.             hr = m_spClientSite->QueryInterface(IID_IOleInPlaceSiteWindowless, (void **)&m_spInPlaceSite);
  434.  
  435.         if (m_spInPlaceSite)
  436.         {
  437.             m_bInPlaceSiteEx = TRUE;
  438.             m_bWndLess = SUCCEEDED(m_spInPlaceSite->CanWindowlessActivate());
  439.             m_bWasOnceWindowless = TRUE;
  440.         }
  441.         else
  442.         {
  443.             m_spClientSite->QueryInterface(IID_IOleInPlaceSiteEx, (void **)&m_spInPlaceSite);
  444.             if (m_spInPlaceSite)
  445.                 m_bInPlaceSiteEx = TRUE;
  446.             else
  447.                 hr = m_spClientSite->QueryInterface(IID_IOleInPlaceSite, (void **)&m_spInPlaceSite);
  448.         }
  449.     }
  450.  
  451.     _ASSERTE(m_spInPlaceSite);
  452.     if (!m_spInPlaceSite)
  453.         return E_FAIL;
  454.  
  455.     m_bNegotiatedWnd = TRUE;
  456.  
  457.     if (!m_bInPlaceActive)
  458.     {
  459.  
  460.         BOOL bNoRedraw = FALSE;
  461.         if (m_bWndLess)
  462.             m_spInPlaceSite->OnInPlaceActivateEx(&bNoRedraw, ACTIVATE_WINDOWLESS);
  463.         else
  464.         {
  465.             if (m_bInPlaceSiteEx)
  466.                 m_spInPlaceSite->OnInPlaceActivateEx(&bNoRedraw, 0);
  467.             else
  468.             {
  469.                 HRESULT hr = m_spInPlaceSite->CanInPlaceActivate();
  470.                 if (FAILED(hr))
  471.                     return hr;
  472.                 m_spInPlaceSite->OnInPlaceActivate();
  473.             }
  474.         }
  475.     }
  476.  
  477.     m_bInPlaceActive = TRUE;
  478.  
  479.     // get location in the parent window,
  480.     // as well as some information about the parent
  481.     //
  482.     OLEINPLACEFRAMEINFO frameInfo;
  483.     RECT rcPos, rcClip;
  484.     CComPtr<IOleInPlaceFrame> spInPlaceFrame;
  485.     CComPtr<IOleInPlaceUIWindow> spInPlaceUIWindow;
  486.     frameInfo.cb = sizeof(OLEINPLACEFRAMEINFO);
  487.     HWND hwndParent;
  488.     if (m_spInPlaceSite->GetWindow(&hwndParent) == S_OK)
  489.     {
  490.         m_spInPlaceSite->GetWindowContext(&spInPlaceFrame,
  491.             &spInPlaceUIWindow, &rcPos, &rcClip, &frameInfo);
  492.  
  493.         if (!m_bWndLess)
  494.         {
  495.             if (m_hWndCD)
  496.             {
  497.                 ShowWindow(m_hWndCD, SW_SHOW);
  498.                         #ifdef BCC32_COMPAT // jmt.  Don't move focus from control to reflector
  499.                                 if (GetFocus()==NULL || !IsChild(m_hWndCD, GetFocus()))
  500.                                            SetFocus(m_hWndCD);
  501.                         #else
  502.                                 SetFocus(m_hWndCD);
  503.                         #endif
  504.             }
  505.             else
  506.             {
  507.                 HWND h = CreateControlWindow(hwndParent, rcPos);
  508.                 _ASSERTE(h == m_hWndCD);
  509.             }
  510.         }
  511.  
  512.         pIPO->SetObjectRects(&rcPos, &rcClip);
  513.     }
  514.  
  515.     CComPtr<IOleInPlaceActiveObject> spActiveObject;
  516.     ControlQueryInterface(IID_IOleInPlaceActiveObject, (void**)&spActiveObject);
  517.  
  518.     // Gone active by now, take care of UIACTIVATE
  519.     if (DoesVerbUIActivate(iVerb))
  520.     {
  521.         if (!m_bUIActive)
  522.         {
  523.             m_bUIActive = TRUE;
  524.             hr = m_spInPlaceSite->OnUIActivate();
  525.             if (FAILED(hr))
  526.                 return hr;
  527.  
  528.             SetControlFocus(TRUE);
  529.             // set ourselves up in the host.
  530.             //
  531.             if (spActiveObject)
  532.             {
  533.                 if (spInPlaceFrame)
  534.                     spInPlaceFrame->SetActiveObject(spActiveObject, NULL);
  535.                 if (spInPlaceUIWindow)
  536.                     spInPlaceUIWindow->SetActiveObject(spActiveObject, NULL);
  537.             }
  538.  
  539.             if (spInPlaceFrame)
  540.                 spInPlaceFrame->SetBorderSpace(NULL);
  541.             if (spInPlaceUIWindow)
  542.                 spInPlaceUIWindow->SetBorderSpace(NULL);
  543.         }
  544.     }
  545.  
  546.     m_spClientSite->ShowObject();
  547.  
  548.     return S_OK;
  549. }
  550.  
  551. HRESULT CComControlBase::IPersistStreamInit_Load(LPSTREAM pStm, ATL_PROPMAP_ENTRY* pMap)
  552. {
  553.     _ASSERTE(pMap != NULL);
  554.     HRESULT hr = S_OK;
  555.     DWORD dwVer;
  556.     hr = pStm->Read(&dwVer, sizeof(DWORD), NULL);
  557.     if (SUCCEEDED(hr) && dwVer <= _ATL_VER)
  558.         hr = pStm->Read(&m_sizeExtent, sizeof(m_sizeExtent), NULL);
  559.     if (FAILED(hr))
  560.         return hr;
  561.  
  562.     CComPtr<IDispatch> pDispatch;
  563.     const IID* piidOld = NULL;
  564.     for(int i = 0; pMap[i].pclsidPropPage != NULL; i++)
  565.     {
  566.         if (pMap[i].szDesc == NULL)
  567.             continue;
  568.         CComVariant var;
  569.  
  570.         HRESULT hr = var.ReadFromStream(pStm);
  571.         if (FAILED(hr))
  572.             break;
  573.  
  574.         if(pMap[i].piidDispatch != piidOld)
  575.         {
  576.             if(FAILED(ControlQueryInterface(*pMap[i].piidDispatch, (void**)&pDispatch)))
  577.             {
  578.                 ATLTRACE(_T("Failed to get a dispatch pointer for property #%i\n"), i);
  579.                 hr = E_FAIL;
  580.                 break;
  581.             }
  582.             piidOld = pMap[i].piidDispatch;
  583.         }
  584.  
  585.         if (FAILED(CComDispatchDriver::PutProperty(pDispatch, pMap[i].dispid, &var)))
  586.         {
  587.             ATLTRACE(_T("Invoked failed on DISPID %x\n"), pMap[i].dispid);
  588.             hr = E_FAIL;
  589.             break;
  590.         }
  591.     }
  592.     return hr;
  593. }
  594.  
  595. HRESULT CComControlBase::IPersistStreamInit_Save(LPSTREAM pStm, BOOL /* fClearDirty */, ATL_PROPMAP_ENTRY* pMap)
  596. {
  597.     _ASSERTE(pMap != NULL);
  598.     DWORD dw = _ATL_VER;
  599.     HRESULT hr = pStm->Write(&dw, sizeof(DWORD), NULL);
  600.     if (FAILED(hr))
  601.         return hr;
  602.     hr = pStm->Write(&m_sizeExtent, sizeof(m_sizeExtent), NULL);
  603.     if (FAILED(hr))
  604.         return hr;
  605.  
  606.     CComPtr<IDispatch> pDispatch;
  607.     const IID* piidOld = NULL;
  608.     for(int i = 0; pMap[i].pclsidPropPage != NULL; i++)
  609.     {
  610.         if (pMap[i].szDesc == NULL)
  611.             continue;
  612.         CComVariant var;
  613.  
  614.         if(pMap[i].piidDispatch != piidOld)
  615.         {
  616.             if(FAILED(ControlQueryInterface(*pMap[i].piidDispatch, (void**)&pDispatch)))
  617.             {
  618.                 ATLTRACE(_T("Failed to get a dispatch pointer for property #%i\n"), i);
  619.                 hr = E_FAIL;
  620.                 break;
  621.             }
  622.             piidOld = pMap[i].piidDispatch;
  623.         }
  624.  
  625.         if (FAILED(CComDispatchDriver::GetProperty(pDispatch, pMap[i].dispid, &var)))
  626.         {
  627.             ATLTRACE(_T("Invoked failed on DISPID %x\n"), pMap[i].dispid);
  628.             hr = E_FAIL;
  629.             break;
  630.         }
  631.  
  632.         HRESULT hr = var.WriteToStream(pStm);
  633.         if (FAILED(hr))
  634.             break;
  635.     }
  636.     if (SUCCEEDED(hr))
  637.         m_bRequiresSave = FALSE;
  638.  
  639.     return hr;
  640. }
  641.  
  642. HRESULT CComControlBase::SendOnDataChange(DWORD advf)
  643. {
  644.     HRESULT hRes = S_OK;
  645.     if (m_spDataAdviseHolder)
  646.     {
  647.         CComPtr<IDataObject> pdo;
  648.         if (SUCCEEDED(ControlQueryInterface(IID_IDataObject, (void**)&pdo)))
  649.             hRes = m_spDataAdviseHolder->SendOnDataChange(pdo, 0, advf);
  650.     }
  651.     return hRes;
  652. }
  653.  
  654. HRESULT CComControlBase::IOleObject_SetClientSite(IOleClientSite *pClientSite)
  655. {
  656.     _ASSERTE(pClientSite == NULL || m_spClientSite == NULL);
  657.     m_spClientSite = pClientSite;
  658.     m_spAmbientDispatch.Release();
  659.     if (m_spClientSite != NULL)
  660.     {
  661.         m_spClientSite->QueryInterface(IID_IDispatch,
  662.             (void**) &m_spAmbientDispatch.p);
  663.     }
  664.     return S_OK;
  665. }
  666.  
  667. HRESULT CComControlBase::IOleObject_GetClientSite(IOleClientSite **ppClientSite)
  668. {
  669.     _ASSERTE(ppClientSite);
  670.     HRESULT hRes = E_POINTER;
  671.     if (ppClientSite != NULL)
  672.     {
  673.         *ppClientSite = m_spClientSite;
  674.         m_spClientSite->AddRef();
  675.         hRes = S_OK;
  676.     }
  677.     return hRes;
  678. }
  679.  
  680. HRESULT CComControlBase::IOleObject_Advise(IAdviseSink *pAdvSink,
  681.     DWORD *pdwConnection)
  682. {
  683.     HRESULT hr = S_OK;
  684.     if (m_spOleAdviseHolder == NULL)
  685.         hr = CreateOleAdviseHolder(&m_spOleAdviseHolder);
  686.     if (SUCCEEDED(hr))
  687.         hr = m_spOleAdviseHolder->Advise(pAdvSink, pdwConnection);
  688.     return hr;
  689. }
  690.  
  691. HRESULT CComControlBase::IOleObject_Close(DWORD dwSaveOption)
  692. {
  693.     CComPtr<IOleInPlaceObject> pIPO;
  694.     ControlQueryInterface(IID_IOleInPlaceObject, (void**)&pIPO);
  695.     _ASSERTE(pIPO != NULL);
  696.     if (m_hWndCD)
  697.     {
  698.         if (m_spClientSite)
  699.             m_spClientSite->OnShowWindow(FALSE);
  700.     }
  701.  
  702.     if (m_bInPlaceActive)
  703.     {
  704.         HRESULT hr = pIPO->InPlaceDeactivate();
  705.         if (FAILED(hr))
  706.             return hr;
  707.         _ASSERTE(!m_bInPlaceActive);
  708.     }
  709.     if (m_hWndCD)
  710.     {
  711.         ATLTRACE(_T("Destroying Window\n"));
  712.         if (::IsWindow(m_hWndCD))
  713.             DestroyWindow(m_hWndCD);
  714.         m_hWndCD = NULL;
  715.     }
  716.  
  717.     // handle the save flag.
  718.     //
  719.     if ((dwSaveOption == OLECLOSE_SAVEIFDIRTY ||
  720.         dwSaveOption == OLECLOSE_PROMPTSAVE) && m_bRequiresSave)
  721.     {
  722.         if (m_spClientSite)
  723.             m_spClientSite->SaveObject();
  724.         SendOnSave();
  725.     }
  726.  
  727.     m_spInPlaceSite.Release();
  728.     m_bNegotiatedWnd = FALSE;
  729.     m_bWndLess = FALSE;
  730.     m_bInPlaceSiteEx = FALSE;
  731.     m_spAdviseSink.Release();
  732.     return S_OK;
  733. }
  734.  
  735. HRESULT CComControlBase::IOleInPlaceObject_InPlaceDeactivate(void)
  736. {
  737.     CComPtr<IOleInPlaceObject> pIPO;
  738.     ControlQueryInterface(IID_IOleInPlaceObject, (void**)&pIPO);
  739.     _ASSERTE(pIPO != NULL);
  740.  
  741.     if (!m_bInPlaceActive)
  742.         return S_OK;
  743.     pIPO->UIDeactivate();
  744.  
  745.     m_bInPlaceActive = FALSE;
  746.  
  747.     // if we have a window, tell it to go away.
  748.     //
  749.     if (m_hWndCD)
  750.     {
  751.         ATLTRACE(_T("Destroying Window\n"));
  752.         if (::IsWindow(m_hWndCD))
  753.             DestroyWindow(m_hWndCD);
  754.         m_hWndCD = NULL;
  755.     }
  756.  
  757.     if (m_spInPlaceSite)
  758.         m_spInPlaceSite->OnInPlaceDeactivate();
  759.  
  760.     return S_OK;
  761. }
  762.  
  763. HRESULT CComControlBase::IOleInPlaceObject_UIDeactivate(void)
  764. {
  765.     // if we're not UIActive, not much to do.
  766.     //
  767.     if (!m_bUIActive)
  768.         return S_OK;
  769.  
  770.     m_bUIActive = FALSE;
  771.  
  772.     // notify frame windows, if appropriate, that we're no longer ui-active.
  773.     //
  774.     CComPtr<IOleInPlaceFrame> spInPlaceFrame;
  775.     CComPtr<IOleInPlaceUIWindow> spInPlaceUIWindow;
  776.     OLEINPLACEFRAMEINFO frameInfo;
  777.     frameInfo.cb = sizeof(OLEINPLACEFRAMEINFO);
  778.     RECT rcPos, rcClip;
  779.  
  780.     HWND hwndParent; 
  781.     // This call to GetWindow is a fix for Delphi
  782.     if (m_spInPlaceSite->GetWindow(&hwndParent) == S_OK)
  783.     {
  784.         m_spInPlaceSite->GetWindowContext(&spInPlaceFrame,
  785.             &spInPlaceUIWindow, &rcPos, &rcClip, &frameInfo);
  786.         if (spInPlaceUIWindow)
  787.             spInPlaceUIWindow->SetActiveObject(NULL, NULL);
  788.         if (spInPlaceFrame)
  789.             spInPlaceFrame->SetActiveObject(NULL, NULL);
  790.     }
  791.     // we don't need to explicitly release the focus here since somebody
  792.     // else grabbing the focus is what is likely to cause us to get lose it
  793.     //
  794.     m_spInPlaceSite->OnUIDeactivate(FALSE);
  795.  
  796.     return S_OK;
  797. }
  798.  
  799. HRESULT CComControlBase::IOleInPlaceObject_SetObjectRects(LPCRECT prcPos,LPCRECT prcClip)
  800. {
  801.     if (prcPos == NULL || prcClip == NULL)
  802.         return E_POINTER;
  803.  
  804.     m_rcPos = *prcPos;
  805.     if (m_hWndCD)
  806.     {
  807.         // the container wants us to clip, so figure out if we really
  808.         // need to
  809.         //
  810.         RECT rcIXect;
  811.         BOOL b = IntersectRect(&rcIXect, prcPos, prcClip);
  812.         HRGN tempRgn = NULL;
  813.         if (b && !EqualRect(&rcIXect, prcPos))
  814.         {
  815.             OffsetRect(&rcIXect, -(prcPos->left), -(prcPos->top));
  816.             tempRgn = CreateRectRgnIndirect(&rcIXect);
  817.         }
  818.  
  819.         SetWindowRgn(m_hWndCD, tempRgn, TRUE);
  820.  
  821.         // set our control's location, but don't change it's size at all
  822.         // [people for whom zooming is important should set that up here]
  823.         //
  824.         SIZEL size = {prcPos->right - prcPos->left, prcPos->bottom - prcPos->top};
  825.         SetWindowPos(m_hWndCD, NULL, prcPos->left,
  826.                      prcPos->top, size.cx, size.cy, SWP_NOZORDER | SWP_NOACTIVATE);
  827.     }
  828.  
  829.     return S_OK;
  830. }
  831.  
  832. HRESULT CComControlBase::IOleObject_SetExtent(DWORD dwDrawAspect, SIZEL *psizel)
  833. {
  834.     if (dwDrawAspect != DVASPECT_CONTENT)
  835.         return DV_E_DVASPECT;
  836.     if (psizel == NULL)
  837.         return E_POINTER;
  838.  
  839.     BOOL bSizeMatchesNatural =
  840.         memcmp(psizel, &m_sizeNatural, sizeof(SIZE)) == 0;
  841.  
  842.     if (m_bAutoSize) //object can't do any other size
  843.         return (bSizeMatchesNatural) ? S_OK : E_FAIL;
  844.  
  845.     BOOL bResized = FALSE;
  846.     if (memcmp(psizel, &m_sizeExtent, sizeof(SIZE)) != 0)
  847.     {
  848.         m_sizeExtent = *psizel;
  849.         bResized = TRUE;
  850.     }
  851.     if (m_bResizeNatural && !bSizeMatchesNatural)
  852.     {
  853.         m_sizeNatural = *psizel;
  854.         bResized = TRUE;
  855.     }
  856.  
  857.     if (m_bRecomposeOnResize && bResized)
  858.     {
  859.         SendOnDataChange();
  860.         FireViewChange();
  861.     }
  862.     return S_OK;
  863. }
  864.  
  865. HRESULT CComControlBase::IViewObject_Draw(DWORD dwDrawAspect, LONG lindex,
  866.     void *pvAspect, DVTARGETDEVICE *ptd, HDC hicTargetDev, HDC hdcDraw,
  867.     LPCRECTL prcBounds, LPCRECTL prcWBounds)
  868. {
  869.     ATLTRACE(_T("Draw dwDrawAspect=%x lindex=%d ptd=%x hic=%x hdc=%x\n"),
  870.         dwDrawAspect, lindex, ptd, hicTargetDev, hdcDraw);
  871. #ifdef _DEBUG
  872.     if (prcBounds == NULL)
  873.         ATLTRACE(_T("\tprcBounds=NULL\n"));
  874.     else
  875.         ATLTRACE(_T("\tprcBounds=%d,%d,%d,%d\n"), prcBounds->left,
  876.             prcBounds->top, prcBounds->right, prcBounds->bottom);
  877.     if (prcWBounds == NULL)
  878.         ATLTRACE(_T("\tprcWBounds=NULL\n"));
  879.     else
  880.         ATLTRACE(_T("\tprcWBounds=%d,%d,%d,%d\n"), prcWBounds->left,
  881.             prcWBounds->top, prcWBounds->right, prcWBounds->bottom);
  882. #endif
  883. #ifdef BCC32_COMPAT
  884.         _ASSERTE(prcBounds != NULL || m_bWndLess);
  885. #else
  886.     _ASSERTE(prcBounds != NULL | m_bWndLess);
  887. #endif
  888.  
  889.     if (prcBounds == NULL)
  890.     {
  891.         if (!m_bWndLess)
  892.             return E_INVALIDARG;
  893.         prcBounds = (RECTL*)&m_rcPos;
  894.     }
  895.  
  896.     // support the aspects required for multi-pass drawing
  897.     switch (dwDrawAspect)
  898.     {
  899.         case DVASPECT_CONTENT:
  900.         case DVASPECT_OPAQUE:
  901.         case DVASPECT_TRANSPARENT:
  902.             break;
  903.         default:
  904.             _ASSERTE(FALSE);
  905.             return DV_E_DVASPECT;
  906. #if !defined(BCC32_COMPAT)
  907.             break;
  908. #endif                        
  909.     }
  910.  
  911.     // make sure nobody forgets to do this
  912.     if (ptd == NULL)
  913.         hicTargetDev = NULL;
  914.  
  915.     BOOL bOptimize = FALSE;
  916.     if (pvAspect && ((DVASPECTINFO *)pvAspect)->cb >= sizeof(DVASPECTINFO))
  917.         bOptimize = (((DVASPECTINFO *)pvAspect)->dwFlags & DVASPECTINFOFLAG_CANOPTIMIZE);
  918.  
  919.     ATL_DRAWINFO di;
  920.     memset(&di, 0, sizeof(di));
  921.     di.cbSize = sizeof(di);
  922.     di.dwDrawAspect = dwDrawAspect;
  923.     di.lindex = lindex;
  924.     di.ptd = ptd;
  925.     di.hicTargetDev = hicTargetDev;
  926.     di.hdcDraw = hdcDraw;
  927.     di.prcBounds = prcBounds;
  928.     di.prcWBounds = prcWBounds;
  929.     di.bOptimize = bOptimize;
  930.     return OnDrawAdvanced(di);
  931. }
  932.  
  933. HRESULT CComControlBase::IDataObject_GetData(FORMATETC *pformatetcIn,
  934.     STGMEDIUM *pmedium)
  935. {
  936.     if (pmedium == NULL)
  937.         return E_POINTER;
  938.     memset(pmedium, 0, sizeof(STGMEDIUM));
  939.     ATLTRACE(_T("Format = %x\n"), pformatetcIn->cfFormat);
  940.     ATLTRACE(_T("TYMED = %x\n"), pformatetcIn->tymed);
  941.  
  942.     if ((pformatetcIn->tymed & TYMED_MFPICT) == 0)
  943.         return DATA_E_FORMATETC;
  944.  
  945.     SIZEL sizeMetric, size;
  946.     if (m_bDrawFromNatural)
  947.         sizeMetric = m_sizeNatural;
  948.     else
  949.         sizeMetric = m_sizeExtent;
  950.     if (!m_bDrawGetDataInHimetric)
  951.         AtlHiMetricToPixel(&sizeMetric, &size);
  952.     else
  953.         size = sizeMetric;
  954.     RECTL rectl = {0 ,0, size.cx, size.cy};
  955.  
  956.     ATL_DRAWINFO di;
  957.     memset(&di, 0, sizeof(di));
  958.     di.cbSize = sizeof(di);
  959.     di.dwDrawAspect = DVASPECT_CONTENT;
  960.     di.lindex = -1;
  961.     di.ptd = NULL;
  962.     di.hicTargetDev = NULL;
  963.     di.prcBounds = &rectl;
  964.     di.prcWBounds = &rectl;
  965.     di.bOptimize = TRUE; //we do a SaveDC/RestoreDC
  966.     di.bRectInHimetric = m_bDrawGetDataInHimetric;
  967.     // create appropriate memory metafile DC
  968.     di.hdcDraw = CreateMetaFile(NULL);
  969.  
  970.     // create attribute DC according to pformatetcIn->ptd
  971.  
  972.     SaveDC(di.hdcDraw);
  973.     SetWindowOrgEx(di.hdcDraw, 0, 0, NULL);
  974.     SetWindowExtEx(di.hdcDraw, rectl.right, rectl.bottom, NULL);
  975.     OnDrawAdvanced(di);
  976.     RestoreDC(di.hdcDraw, -1);
  977.  
  978.     HMETAFILE hMF = CloseMetaFile(di.hdcDraw);
  979.     if (hMF == NULL)
  980.         return E_UNEXPECTED;
  981.  
  982.     HGLOBAL hMem=GlobalAlloc(GMEM_SHARE | GMEM_MOVEABLE, sizeof(METAFILEPICT));
  983.  
  984.     if (NULL==hMem)
  985.     {
  986.         DeleteMetaFile(hMF);
  987.         return ResultFromScode(STG_E_MEDIUMFULL);
  988.     }
  989.  
  990.     LPMETAFILEPICT pMF=(LPMETAFILEPICT)GlobalLock(hMem);
  991.     pMF->hMF=hMF;
  992.     pMF->mm=MM_ANISOTROPIC;
  993.     pMF->xExt=sizeMetric.cx;
  994.     pMF->yExt=sizeMetric.cy;
  995.     GlobalUnlock(hMem);
  996.  
  997.     pmedium->tymed = TYMED_MFPICT;
  998.     pmedium->hGlobal = hMem;
  999.     pmedium->pUnkForRelease = NULL;
  1000.  
  1001.     return S_OK;
  1002.  
  1003. }
  1004.  
  1005. HRESULT CComControlBase::FireViewChange()
  1006. {
  1007.     if (m_bInPlaceActive)
  1008.     {
  1009.         // Active
  1010.         if (m_hWndCD != NULL)
  1011.             return ::InvalidateRect(m_hWndCD, NULL, TRUE); // Window based
  1012.         if (m_spInPlaceSite != NULL)
  1013.             return m_spInPlaceSite->InvalidateRect(NULL, TRUE); // Windowless
  1014.     }
  1015.     // Inactive
  1016.     SendOnViewChange(DVASPECT_CONTENT);
  1017.     return S_OK;
  1018. }
  1019.  
  1020. void CComControlBase::GetZoomInfo(ATL_DRAWINFO& di)
  1021. {
  1022.     const RECTL& rcPos = *di.prcBounds;
  1023.     SIZEL sizeDen;
  1024.     if (m_bDrawFromNatural)
  1025.         sizeDen = m_sizeNatural;
  1026.     else
  1027.         sizeDen = m_sizeExtent;
  1028.     if (!di.bRectInHimetric)
  1029.         AtlHiMetricToPixel(&sizeDen, &sizeDen);
  1030.     SIZEL sizeNum = {rcPos.right-rcPos.left, rcPos.bottom-rcPos.top};
  1031.     di.ZoomNum.cx = sizeNum.cx;
  1032.     di.ZoomNum.cy = sizeNum.cy;
  1033.     di.ZoomDen.cx = sizeDen.cx;
  1034.     di.ZoomDen.cy = sizeDen.cy;
  1035.     if (sizeDen.cx == 0 || sizeDen.cy == 0 ||
  1036.         sizeNum.cx == 0 || sizeNum.cy == 0)
  1037.     {
  1038.         di.ZoomNum.cx = di.ZoomNum.cy = di.ZoomDen.cx = di.ZoomDen.cy = 1;
  1039.         di.bZoomed = FALSE;
  1040.     }
  1041.     else if (sizeNum.cx != sizeDen.cx || sizeNum.cy != sizeDen.cy)
  1042.         di.bZoomed = TRUE;
  1043.     else
  1044.         di.bZoomed = FALSE;
  1045. }
  1046.  
  1047. HRESULT CComControlBase::OnDrawAdvanced(ATL_DRAWINFO& di)
  1048. {
  1049.     BOOL bDeleteDC = FALSE;
  1050.     if (di.hicTargetDev == NULL)
  1051.     {
  1052.         di.hicTargetDev = AtlCreateTargetDC(di.hdcDraw, di.ptd);
  1053.         bDeleteDC = (di.hicTargetDev != di.hdcDraw);
  1054.     }
  1055.     RECTL rectBoundsDP = *di.prcBounds;
  1056.     BOOL bMetafile = GetDeviceCaps(di.hdcDraw, TECHNOLOGY) == DT_METAFILE;
  1057.     if (!bMetafile)
  1058.     {
  1059.         ::LPtoDP(di.hicTargetDev, (LPPOINT)&rectBoundsDP, 2);
  1060.         SaveDC(di.hdcDraw);
  1061.         SetMapMode(di.hdcDraw, MM_TEXT);
  1062.         SetWindowOrgEx(di.hdcDraw, 0, 0, NULL);
  1063.         SetViewportOrgEx(di.hdcDraw, 0, 0, NULL);
  1064.         di.bOptimize = TRUE; //since we save the DC we can do this
  1065.     }
  1066.     di.prcBounds = &rectBoundsDP;
  1067.     GetZoomInfo(di);
  1068.  
  1069.     HRESULT hRes = OnDraw(di);
  1070.     if (bDeleteDC)
  1071.         ::DeleteDC(di.hicTargetDev);
  1072.     if (!bMetafile)
  1073.         RestoreDC(di.hdcDraw, -1);
  1074.     return hRes;
  1075. }
  1076.  
  1077. LRESULT CComControlBase::OnPaint(UINT /* nMsg */, WPARAM /* wParam */,
  1078.     LPARAM /* lParam */, BOOL& /* lResult */)
  1079. {
  1080.     RECT rc;
  1081.     PAINTSTRUCT ps;
  1082.  
  1083.     HDC hdc = ::BeginPaint(m_hWndCD, &ps);
  1084.     if (hdc == NULL)
  1085.         return 0;
  1086.     ::GetClientRect(m_hWndCD, &rc);
  1087.  
  1088.     ATL_DRAWINFO di;
  1089.     memset(&di, 0, sizeof(di));
  1090.     di.cbSize = sizeof(di);
  1091.     di.dwDrawAspect = DVASPECT_CONTENT;
  1092.     di.lindex = -1;
  1093.     di.hdcDraw = hdc;
  1094.     di.prcBounds = (LPCRECTL)&rc;
  1095.  
  1096.     OnDrawAdvanced(di);
  1097.     ::EndPaint(m_hWndCD, &ps);
  1098.     return 0;
  1099. }
  1100.  
  1101. #ifndef ATL_NO_NAMESPACE
  1102. }; //namespace ATL
  1103. #endif
  1104.  
  1105. ///////////////////////////////////////////////////////////////////////////////
  1106. //All Global stuff goes below this line
  1107. ///////////////////////////////////////////////////////////////////////////////
  1108.  
  1109. #ifndef _ATL_DLL
  1110. ATLAPI_(HDC) AtlCreateTargetDC(HDC hdc, DVTARGETDEVICE* ptd)
  1111. {
  1112.     USES_CONVERSION;
  1113.  
  1114.     // cases  hdc, ptd, hdc is metafile, hic
  1115. //  NULL,    NULL,  n/a,    Display
  1116. //  NULL,   !NULL,  n/a,    ptd
  1117. //  !NULL,   NULL,  FALSE,  hdc
  1118. //  !NULL,   NULL,  TRUE,   display
  1119. //  !NULL,  !NULL,  FALSE,  ptd
  1120. //  !NULL,  !NULL,  TRUE,   ptd
  1121.  
  1122.     if (ptd != NULL)
  1123.     {
  1124.         LPDEVMODEOLE lpDevMode;
  1125.         LPOLESTR lpszDriverName;
  1126.         LPOLESTR lpszDeviceName;
  1127.         LPOLESTR lpszPortName;
  1128.  
  1129.         if (ptd->tdExtDevmodeOffset == 0)
  1130.             lpDevMode = NULL;
  1131.         else
  1132.             lpDevMode  = (LPDEVMODEOLE) ((LPSTR)ptd + ptd->tdExtDevmodeOffset);
  1133.  
  1134.         lpszDriverName = (LPOLESTR)((BYTE*)ptd + ptd->tdDriverNameOffset);
  1135.         lpszDeviceName = (LPOLESTR)((BYTE*)ptd + ptd->tdDeviceNameOffset);
  1136.         lpszPortName   = (LPOLESTR)((BYTE*)ptd + ptd->tdPortNameOffset);
  1137.  
  1138.         return ::CreateDC(OLE2CT(lpszDriverName), OLE2CT(lpszDeviceName),
  1139.             OLE2CT(lpszPortName), DEVMODEOLE2T(lpDevMode));
  1140.     }
  1141.     else if (hdc == NULL || GetDeviceCaps(hdc, TECHNOLOGY) == DT_METAFILE)
  1142.         return ::CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
  1143.     else
  1144.         return hdc;
  1145. }
  1146.  
  1147. #define HIMETRIC_PER_INCH   2540
  1148. #define MAP_PIX_TO_LOGHIM(x,ppli)   ( (HIMETRIC_PER_INCH*(x) + ((ppli)>>1)) / (ppli) )
  1149. #define MAP_LOGHIM_TO_PIX(x,ppli)   ( ((ppli)*(x) + HIMETRIC_PER_INCH/2) / HIMETRIC_PER_INCH )
  1150.  
  1151. ATLAPI_(void) AtlHiMetricToPixel(const SIZEL * lpSizeInHiMetric, LPSIZEL lpSizeInPix)
  1152. {
  1153.     int nPixelsPerInchX;    // Pixels per logical inch along width
  1154.     int nPixelsPerInchY;    // Pixels per logical inch along height
  1155.  
  1156.     HDC hDCScreen = GetDC(NULL);
  1157.     _ASSERTE(hDCScreen != NULL);
  1158.     nPixelsPerInchX = GetDeviceCaps(hDCScreen, LOGPIXELSX);
  1159.     nPixelsPerInchY = GetDeviceCaps(hDCScreen, LOGPIXELSY);
  1160.     ReleaseDC(NULL, hDCScreen);
  1161.  
  1162.     lpSizeInPix->cx = MAP_LOGHIM_TO_PIX(lpSizeInHiMetric->cx, nPixelsPerInchX);
  1163.     lpSizeInPix->cy = MAP_LOGHIM_TO_PIX(lpSizeInHiMetric->cy, nPixelsPerInchY);
  1164. }
  1165.  
  1166. ATLAPI_(void) AtlPixelToHiMetric(const SIZEL * lpSizeInPix, LPSIZEL lpSizeInHiMetric)
  1167. {
  1168.     int nPixelsPerInchX;    // Pixels per logical inch along width
  1169.     int nPixelsPerInchY;    // Pixels per logical inch along height
  1170.  
  1171.     HDC hDCScreen = GetDC(NULL);
  1172.     _ASSERTE(hDCScreen != NULL);
  1173.     nPixelsPerInchX = GetDeviceCaps(hDCScreen, LOGPIXELSX);
  1174.     nPixelsPerInchY = GetDeviceCaps(hDCScreen, LOGPIXELSY);
  1175.     ReleaseDC(NULL, hDCScreen);
  1176.  
  1177.     lpSizeInHiMetric->cx = MAP_PIX_TO_LOGHIM(lpSizeInPix->cx, nPixelsPerInchX);
  1178.     lpSizeInHiMetric->cy = MAP_PIX_TO_LOGHIM(lpSizeInPix->cy, nPixelsPerInchY);
  1179. }
  1180. #endif
  1181.